/**
 * Copyright 2013-2025 the original author or authors from the JHipster project.
 *
 * This file is part of the JHipster project, see https://www.jhipster.tech/
 * for more information.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { asPostWritingEntitiesTask, asWriteEntityFilesSection, asWritingEntitiesTask } from '../base-application/support/index.ts';
import { clientApplicationTemplatesBlock } from '../client/support/files.ts';
import { filterEntitiesAndPropertiesForClient, filterEntitiesForClient } from '../client/support/filter-entities.ts';

import type { Application as AngularApplication, Entity as AngularEntity, Source as AngularSource } from './types.ts';

const entityModelFiles = clientApplicationTemplatesBlock({
  templates: ['entities/_entityFolder_/_entityFile_.model.ts', 'entities/_entityFolder_/_entityFile_.test-samples.ts'],
});

const entityServiceFiles = clientApplicationTemplatesBlock({
  condition: generator => !generator.embedded,
  templates: ['entities/_entityFolder_/service/_entityFile_.service.ts', 'entities/_entityFolder_/service/_entityFile_.service.spec.ts'],
});

export const builtInFiles = asWriteEntityFilesSection({
  model: [entityModelFiles],
  service: [entityServiceFiles],
});

export const angularFiles = {
  model: [entityModelFiles],
  service: [entityServiceFiles],
  client: [
    clientApplicationTemplatesBlock({
      condition: generator => !generator.embedded,
      templates: [
        'entities/_entityFolder_/_entityFile_.routes.ts',
        'entities/_entityFolder_/detail/_entityFile_-detail.html',
        'entities/_entityFolder_/detail/_entityFile_-detail.ts',
        'entities/_entityFolder_/detail/_entityFile_-detail.spec.ts',
        'entities/_entityFolder_/list/_entityFile_.html',
        'entities/_entityFolder_/list/_entityFile_.ts',
        'entities/_entityFolder_/list/_entityFile_.spec.ts',
        'entities/_entityFolder_/route/_entityFile_-routing-resolve.service.ts',
        'entities/_entityFolder_/route/_entityFile_-routing-resolve.service.spec.ts',
      ],
    }),
    clientApplicationTemplatesBlock({
      condition: generator => !generator.readOnly && !generator.embedded,
      templates: [
        'entities/_entityFolder_/update/_entityFile_-form.service.ts',
        'entities/_entityFolder_/update/_entityFile_-form.service.spec.ts',
        'entities/_entityFolder_/update/_entityFile_-update.html',
        'entities/_entityFolder_/update/_entityFile_-update.spec.ts',
        'entities/_entityFolder_/delete/_entityFile_-delete-dialog.html',
        'entities/_entityFolder_/update/_entityFile_-update.ts',
        'entities/_entityFolder_/delete/_entityFile_-delete-dialog.ts',
        'entities/_entityFolder_/delete/_entityFile_-delete-dialog.spec.ts',
      ],
    }),
  ],
};

export const userManagementFiles = asWriteEntityFilesSection({
  userManagement: [
    clientApplicationTemplatesBlock({
      templates: [
        'admin/user-management/user-management.route.ts',
        'admin/user-management/user-management.model.ts',
        'admin/user-management/list/user-management.html',
        'admin/user-management/list/user-management.spec.ts',
        'admin/user-management/list/user-management.ts',
        'admin/user-management/detail/user-management-detail.html',
        'admin/user-management/detail/user-management-detail.spec.ts',
        'admin/user-management/detail/user-management-detail.ts',
        'admin/user-management/update/user-management-update.html',
        'admin/user-management/update/user-management-update.spec.ts',
        'admin/user-management/update/user-management-update.ts',
        'admin/user-management/delete/user-management-delete-dialog.html',
        'admin/user-management/delete/user-management-delete-dialog.spec.ts',
        'admin/user-management/delete/user-management-delete-dialog.ts',
        'admin/user-management/service/user-management.service.spec.ts',
        'admin/user-management/service/user-management.service.ts',
      ],
    }),
  ],
});

export const writeEntitiesFiles = asWritingEntitiesTask<AngularEntity, AngularApplication<AngularEntity>>(async function ({
  application,
  entities,
}) {
  for (const entity of (application.filterEntitiesAndPropertiesForClient ?? filterEntitiesAndPropertiesForClient)(entities)) {
    if (entity.builtInUser) {
      await this.writeFiles({
        sections: builtInFiles,
        context: {
          ...application,
          ...entity,
          fields: entity.fields.filter(field => ['id', 'login'].includes(field.fieldName)),
          readOnly: true,
        },
      });

      if (application.generateUserManagement && application.userManagement!.skipClient) {
        await this.writeFiles({
          sections: userManagementFiles,
          context: {
            ...application,
            ...entity,
            i18nKeyPrefix: 'userManagement',
            entityFileName: 'user-management',
            entityFolderPrefix: 'admin',
          },
        });
      }
    } else {
      await this.writeFiles({
        sections: entity.entityClientModelOnly ? { model: [entityModelFiles] } : angularFiles,
        context: { ...application, ...entity },
      });
    }
  }
});

export const postWriteEntitiesFiles = asPostWritingEntitiesTask<AngularEntity, AngularApplication<AngularEntity>, AngularSource>(
  async function (this, taskParam) {
    const { application, source } = taskParam;
    const entities = (application.filterEntitiesForClient ?? filterEntitiesForClient)(taskParam.entities).filter(
      entity => !entity.builtInUser && !entity.embedded && !entity.entityClientModelOnly,
    );
    source.addEntitiesToClient({ ...taskParam, entities });
  },
);

export const cleanupEntitiesFiles = asWritingEntitiesTask<AngularEntity, AngularApplication<AngularEntity>>(function ({
  application,
  entities,
  control,
}) {
  for (const entity of (application.filterEntitiesForClient ?? filterEntitiesForClient)(entities).filter(entity => !entity.builtIn)) {
    const { entityFolderName, entityFileName, name: entityName } = entity;
    if (control.isJhipsterVersionLessThan('5.0.0')) {
      this.removeFile(`${application.clientSrcDir}app/entities/${entityName}/${entityName}.model.ts`);
    }

    if (control.isJhipsterVersionLessThan('6.3.0')) {
      this.removeFile(`${application.clientSrcDir}app/entities/${entityFolderName}/index.ts`);
    }

    if (control.isJhipsterVersionLessThan('7.0.0-beta.0')) {
      this.removeFile(`${application.clientSrcDir}/app/entities/${entityFolderName}/${entityFileName}.route.ts`);
      this.removeFile(`${application.clientSrcDir}/app/entities/${entityFolderName}/${entityFileName}.ts`);
      this.removeFile(`${application.clientSrcDir}/app/entities/${entityFolderName}/${entityFileName}.html`);
      this.removeFile(`${application.clientSrcDir}/app/entities/${entityFolderName}/${entityFileName}-detail.ts`);
      this.removeFile(`${application.clientSrcDir}/app/entities/${entityFolderName}/${entityFileName}-detail.html`);
      this.removeFile(`${application.clientSrcDir}/app/entities/${entityFolderName}/${entityFileName}-delete-dialog.ts`);
      this.removeFile(`${application.clientSrcDir}/app/entities/${entityFolderName}/${entityFileName}-delete-dialog.html`);
      this.removeFile(`${application.clientSrcDir}/app/entities/${entityFolderName}/${entityFileName}-update.ts`);
      this.removeFile(`${application.clientSrcDir}/app/entities/${entityFolderName}/${entityFileName}-update.html`);
      this.removeFile(`${application.clientSrcDir}/app/shared/model/${entity.entityModelFileName}.model.ts`);
      entity.fields.forEach(field => {
        if (field.fieldIsEnum) {
          const { enumFileName } = field;
          this.removeFile(`${application.clientSrcDir}/app/shared/model/enumerations/${enumFileName}.model.ts`);
        }
      });
      this.removeFile(`${application.clientSrcDir}/app/entities/${entityFolderName}/${entityFileName}-routing-resolve.service.ts`);
      this.removeFile(`${application.clientSrcDir}/app/entities/${entityFolderName}/${entityFileName}-routing.module.ts`);
      this.removeFile(`${application.clientSrcDir}/app/entities/${entityFolderName}/${entityFileName}.service.ts`);
      this.removeFile(`${application.clientSrcDir}/app/entities/${entityFolderName}/${entityFileName}.service.spec.ts`);
      this.removeFile(`${application.clientTestDir}/spec/app/entities/${entityFolderName}/${entityFileName}.spec.ts`);
      this.removeFile(`${application.clientTestDir}/spec/app/entities/${entityFolderName}/${entityFileName}-detail.spec.ts`);
      this.removeFile(`${application.clientTestDir}/spec/app/entities/${entityFolderName}/${entityFileName}-delete-dialog.spec.ts`);
      this.removeFile(`${application.clientTestDir}/spec/app/entities/${entityFolderName}/${entityFileName}-update.spec.ts`);
      this.removeFile(`${application.clientTestDir}/spec/app/entities/${entityFolderName}/${entityFileName}.service.spec.ts`);
    }

    if (control.isJhipsterVersionLessThan('7.10.0')) {
      this.removeFile(`${application.clientSrcDir}app/entities/${entityFolderName}/${entityFileName}.module.ts`);
      this.removeFile(`${application.clientSrcDir}app/entities/${entityFolderName}/route/${entityFileName}-routing.module.ts`);
    }

    if (control.isJhipsterVersionLessThan('8.12.0')) {
      this.removeFile(`${application.clientSrcDir}app/entities/${entityFolderName}/delete/${entityFileName}-delete-dialog.component.html`);
      this.removeFile(
        `${application.clientSrcDir}app/entities/${entityFolderName}/delete/${entityFileName}-delete-dialog.component.spec.ts`,
      );
      this.removeFile(`${application.clientSrcDir}app/entities/${entityFolderName}/delete/${entityFileName}-delete-dialog.component.ts`);
      this.removeFile(`${application.clientSrcDir}app/entities/${entityFolderName}/detail/${entityFileName}-detail.component.html`);
      this.removeFile(`${application.clientSrcDir}app/entities/${entityFolderName}/detail/${entityFileName}-detail.component.spec.ts`);
      this.removeFile(`${application.clientSrcDir}app/entities/${entityFolderName}/detail/${entityFileName}-detail.component.ts`);
      this.removeFile(`${application.clientSrcDir}app/entities/${entityFolderName}/list/${entityFileName}.component.html`);
      this.removeFile(`${application.clientSrcDir}app/entities/${entityFolderName}/list/${entityFileName}.component.spec.ts`);
      this.removeFile(`${application.clientSrcDir}app/entities/${entityFolderName}/list/${entityFileName}.component.ts`);
      this.removeFile(`${application.clientSrcDir}app/entities/${entityFolderName}/update/${entityFileName}-update.component.html`);
      this.removeFile(`${application.clientSrcDir}app/entities/${entityFolderName}/update/${entityFileName}-update.component.spec.ts`);
      this.removeFile(`${application.clientSrcDir}app/entities/${entityFolderName}/update/${entityFileName}-update.component.ts`);
    }
  }
});
